﻿using AuSys.Services.App.ConfigReader.Abstractions;

namespace AuSys.Services.App.ConfigReader
{
    public class UserAccessScopeConfigReader(
        IConfiguration configuration
        ): IConfigReader<UserAccessScopeConfig>
    {
        private static UserAccessScopeConfig? perScopeConfigs = null;
        private readonly static Lock perScopeConfigReadingLock = new();
        public UserAccessScopeConfig Get()
        {
            lock (perScopeConfigReadingLock)
            {
                if (perScopeConfigs is not null)
                    return perScopeConfigs;
                var cfgSection = configuration.GetSection(userAccessScopeConfigKey);
                perScopeConfigs = new();
                cfgSection.Bind(perScopeConfigs);
                return perScopeConfigs;
            }
        }
        private const string userAccessScopeConfigKey = "UserAccessScope";

        public bool ScopeContainsUser(string scope, int userId)
        {
            var cfg = Get();
            var s = cfg.PerScope
                .Where(x => x.MatchName(scope))
                .FirstOrDefault();
            return s?.ContainUser(userId) ?? false;
        }
    }

    public class UserAccessScopeConfig
    {
        public List<int> DefaultRejectUserIds { get; set; } = [];
        public List<PerScopeConfig> PerScope { get; set; } = [];
        public bool NoNeed =>
            DefaultRejectUserIds.Count == 0
            && PerScope.Count == 0;
        public class PerScopeConfig
        {
            public string? Scope { get; set; }
            public bool Flag { get; set; }
            public List<int>? UserIds { get; set; }
            public bool UserAll { get; set; }

            public bool MatchName(string scopeName)
                => string.Equals(Scope, scopeName, StringComparison.OrdinalIgnoreCase);
            public bool ContainUser(int userId)
                => UserAll || (UserIds?.Contains(userId) ?? false);
        }
    }
}
